﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "IGraphicsNodeReference.h"
#include "GcmpDbCommonEdit.h"
namespace gcmp
{

    class IDocument;
    class IPlane;

    /// \brief 对齐操作类型
    enum EnAlignmentOperationTypes
    {
        EAOM_UNKNOW = 0,        ///<未知类型
        EAOM_TRANSLATE,         ///<平移
        EAOM_ROTATE,            ///<旋转
        EAOM_TRIM_OR_EXTEND,    ///<裁剪或延伸
        EAOM_NOT_ALLOWED        ///<不允许
    };

    /// \brief 对齐操作结果错误码
    enum EnAlignmentOperationErrors
    {
        EAOE_UNKNOW = 0,                                ///<未知类型
        EAOE_PERPENDICULAR_CANNOT_TRANSFORM,            ///<垂直不能变换
        EAOE_NOT_PERPENDICULAR_CANNOT_TRANSFORM,        ///<不垂直也不能变换
        EAOE_FAILED,                                    ///<失败
        EAOE_BUILDIN_REFERENCE_PLANE_CANNOT_TRANSFORM,  ///< 内置参照平面不支持变换
        EAOE_NO_ERROR                                   ///<没有错误
    };

    /// \brief 对齐操作接口
    class GCMP_DB_COMMON_EDIT_EXPORT AlignmentUtils
    {
    public:
        /// \brief 对齐图形节点引用对象
        /// \param pDocument      图形所属的文档
        /// \param pWorkPlane     工作平面
        /// \param gnodeReference1  目标图形节点引用
        /// \param gnodeReference2  被变换的图形节点引用
        /// \param distance   移动的距离
        /// \param eError   对齐操作结果错误码
        /// \param epsilon 比较的容差
        /// \return  是否对齐成功
        /// \note 为了实现构件之间的对齐操作，有可能会修改对齐构件的几何体的大小或形状    

        static bool AlignGraphicsNodeReference(IDocument* pDocument, const IPlane* pWorkPlane, const IGraphicsNodeReference& gnodeReference1,
            const IGraphicsNodeReference& gnodeReference2, double distance, EnAlignmentOperationErrors& eError, double epsilon = Constants::DOUBLE_EPS);

        /// \brief 计算两个图形节点对齐需要做的矩阵变换
        /// \param pDocument      图形所属的文档
        /// \param pWorkPlane     工作平面
        /// \param gnodeReference1  目标图形节点引用
        /// \param gnodeReference2  做对齐计算的图形节点引用
        /// \param distance   移动的距离
        /// \param eError   对齐操作结果错误码
        /// \return  是否对齐成功
        static Matrix4d ComputeMatrixForNodeReferenceAlignment(const IDocument* pDocument, const IPlane* pWorkPlane,
            const IGraphicsNodeReference& gnodeReference1, const IGraphicsNodeReference& gnodeReference2,
            double distance, EnAlignmentOperationErrors& eError);

        /// \brief 选择对齐操作类型
        /// \param pDoc 对齐操作文档
        /// \param gnodeReference1  目标图形节点引用
        /// \param gnodeReference2  被变换的图形节点引用
        /// \param eError   对齐操作结果错误码
        /// \return   判定的对齐操作类型
        static EnAlignmentOperationTypes JudgeAlignmentOperationType(const IDocument* pDoc, const IGraphicsNodeReference& gnodeReference1, const IGraphicsNodeReference& gnodeReference2, EnAlignmentOperationErrors& eError, double epsilon = Constants::DOUBLE_EPS);

        /// \brief 旋转方式对齐
        /// \param pDoc 对齐操作文档
        /// \param gnodeReference1    目标图形节点引用
        /// \param gnodeReference2    被变换的图形节点引用
        /// \param distance  平移距离
        /// \return 是否成功执行该对齐变换
        static bool RotateForAlignment(const IDocument* pDoc, const IGraphicsNodeReference& gnodeReference1, const IGraphicsNodeReference& gnodeReference2, double distance);

        /// \brief 平移方式对齐
        /// \param pDoc 对齐操作文档
        /// \param gnodeReference1    目标图形节点引用
        /// \param gnodeReference2    被变换的图形节点引用
        /// \param distance  平移距离
        /// \return 是否成功执行该对齐变换
        /// \note 平移前有可能会会对几何体的大小或形状做修改
        static bool TranslateForAlignment(const IDocument* pDoc, const IGraphicsNodeReference& gnodeReference1, const IGraphicsNodeReference& gnodeReference2, double distance);

        /// \brief 裁剪或延伸方式对齐
        /// \param pDoc 对齐操作文档  
        /// \param gnodeReference1  目标图形节点引用
        /// \param gnodeReference2  被变换的图形节点引用
        /// \return 是否成功执行该对齐变换
        static bool TrimOrExtendForAlignment(const IDocument* pDoc, const IGraphicsNodeReference& gnodeReference1, const IGraphicsNodeReference& gnodeReference2);

    };
}
